home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
001-100
/
001-025
/
001
/
colorful
/
colorful.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-17
|
19KB
|
490 lines
/*
* Article 582 of net.micro.amiga:
* ion: version B 2.10.2 9/17/84 chuqui version 1.9 3/12/85; site unisoft.UUCP
* Posting-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site amiga.amiga.UUCP
* Path: unisoft!dual!vecpyr!lll-lcc!lll-crg!seismo!hao!hplabs!pesnta!greipa!decwrl!pyramid!amiga!bobp
* From: bobp@amiga.UUCP (Robert S. Pariseau)
* Newsgroups: net.micro.amiga
* Subject: More Fun with 6 Planes (LONG SOURCE)
* Message-ID: <223@amiga.amiga.UUCP>
* Date: 11 Nov 85 10:39:27 GMT
* Date-Received: 14 Nov 85 21:00:59 GMT
* Reply-To: bobp@snake.UUCP (Robert S. Pariseau)
* Organization: Commodore-Amiga Inc., 983 University Ave #D, Los Gatos CA 95030
* Lines: 471
*
* TITLE: More Fun with 6 Planes (LONG SOURCE)
*
* The source below is a bit of eye-candy that shows off the use of Hold
* and Modify graphics display mode on the Amiga. Hold and Modify (or HAM
* for short) is a compromise between the limited direct color access of
* an inexpensive color-palette, frame buffer graphics engine like the
* Amiga, and the high cost of a direct reading frame buffer graphic engine
* like some of the more expensive CAD systems. On the Amiga, the bits
* associated with a given pixel select one of the 32 color registers. Each
* color register contains a color value consisting of 4 bits of Red
* component, 4 bits of Green, and 4 bits of Blue -- yielding 4096 different
* colors from black to white. The Amiga hardware has sufficient bandwidth
* to retrieve 6 bit-planes worth of data for a given pixel (4 in high
* resolution display). The combination of these two constraints says that
* in a static display (no dynamic color changing going on in the
* background), you can display up to 32 colors simultaneously in low
* res and up to 16 colors simultaneously in highs res choosen out of
* the palette of 4096 possible colors.
*
* [Note: as discussed earlier, you can actually get up to 64 distinct
* colors in low res using 6 planes and EXTRA_HALFBRITE display mode.
* Further, note that dynamic color changing goes on all the time in
* normal Amiga displays -- that's how each of the separately slideable
* screens gets its own color palette for instance.]
*
* If the Amiga were only somehow capable of pulling in 12 planes of data
* per pixel, then we could avoid using the color palette altogether. We
* could encode the desired pixel color (4 bits each R, G, and B) directly
* into the frame buffer. This would allow us to independently choose
* any of the 4096 colors for each pixel -- with no limit on how many
* different colors appeared in a given display.
*
* [Note: there's a downside to this as well. Since the display doesn't
* feed through a color palette, there's no easy way of swapping or
* changing colors in your picture -- you have to actually go out and
* change all those pixels. With a color palette, you just change the
* color values in the registers. This trick is fundamental to the
* technique of "color cycle animation".]
*
* HAM is a color modulation technique which approaches the flexibility
* of a direct reading frame buffer. Using HAM, you can specify any
* desired color out of the 4096 available within 3 horizontally
* adjacent pixels. Here is how it works.
*
* Consider a 4 plane image. The 4 bits of each pixel select one of the
* first 16 color registers. Now consider the extra 2 bits per pixel
* of a 6 plane HAM image. Those extra 2 bits are used as control bits,
* selecting between the following 4 choices:
*
* 0) Use the lower 4 bits as a color register selector, just as normal.
*
* 1) Use the lower 4 bits as the Blue component of the color for this
* pixel. Copy the Red and Green components of the color for this
* pixel from the color of the Playfield pixel immediately to the
* left of this one.
*
* 2) Use the lower 4 bits as the Red component of the color for this
* pixel. Copy the Blue and Green components of the color for this
* pixel from the color of the Playfield pixel immediately to the
* left of this one.
*
* 3) Use the lower 4 bits as the Green component of the color for this
* pixel. Copy the Red and Blue components of the color for this
* pixel from the color of the Playfield pixel immediately to the
* left of this one.
*
* Note that only the color produced for the pixel is varied. The contents
* of the color registers themselves are NOT changed by HAM. Also note
* that the effects are cumulative. Thus, in 3 adjacent pixels, you can
* Modify-Red, Modify-Green, and Modify-Blue, thereby producing any color
* you want.
*
* Finally, note that a Modify-x pixel takes its "Hold" colors from the
* color that is OR WOULD HAVE BEEN produced for the PLAYFIELD (i.e.,
* frame buffer) pixel immediately to its left. This means that sprite
* images moving over the display do NOT mess up your carefully choosen
* HAM colors.
*
* There is a hardware mode bit that controls HAM. A HAM display requires
* 5 or 6 bit planes. If you provide a 5 plane image, the hardware assumes
* a 6th bit value of 0 for each pixel -- this means you can only choose
* normal and Modify-Blue out of the choices above.
*
* The graphics kernel software automatically supports HAM as a ViewPort
* attribute. That means that each of your separately slideable ViewPorts
* (Screens in Intuition lingo) can have, or not have, HAM turned on without
* affecting the others.
*
* BEWARE! Some of the older developer machines and store demo machines
* do not produce reliable HAM images. ALL of the consumer machines do
* HAM just fine.
*/
/*
* ----------------------------Program Notes:
*
* The Colorful program will compile and link cleanly using the native
* Amiga Lattice C tools on the standard V1.0 C disk. The Make script
* in the examples directory will do all the work for you. As usual,
* I recommend that you copy the source into ram: disk and then direct
* Make at it by typing:
*
* 1> execute Make ram:Colorful
*
* The program displays 256 boxes each having a different color out of
* the possible 4096. Colorful listens for left mouse button events
* and switches between two display modes. The first is an ordered
* display with labelled color components. The second is a random
* display where boxes randomly selected have their color randomly
* changed. Note that at no time do any 2 boxes share the same color.
*
* If you are sharp-eyed, you will notice a narrow stripe of red and a
* narrow stripe of green at the leading (leftmost) edge of each of the
* boxes. These are the color modifiers in action. Each box consists
* of a vertical line of Modify-Red, followed by a vertical line of
* Modify-Green, followed by a rectangle of Modify-Blue as follows:
*
* RGBBBBBBBBB
* RGBBBBBBBBB
* RGBBBBBBBBB
* RGBBBBBBBBB
* RGBBBBBBBBB
* RGBBBBBBBBB
*
* The routine hamBox() produces such a box.
*
* For further information, see the Amiga Hardware Manual, the Amiga
* ROM Kernel Manual, and the manual Intuition: The Amiga User Interface.
*
* ----------------------------Program Source Follows:
*
*/
/***********************************************************************
* Colorful -- A demo of the Amiga's Hold and Modify mode, showing, at
* all times, a different subset of 256 of the 4096
* colors available on the Amiga. At any moment, no two
* squares have the same exact color in them.
*
* Rob Peck -- November 5, 1985
* Bob Pariseau -- November 10, 1985 (Rework for tutorial)
*
**********************************************************************/
#include <exec/types.h>
#include <exec/tasks.h>
#include <exec/libraries.h>
#include <exec/devices.h>
#include <devices/keymap.h>
#include <graphics/copper.h>
#include <graphics/display.h>
#include <graphics/gfxbase.h>
#include <graphics/text.h>
#include <graphics/view.h>
#include <graphics/gels.h>
#include <graphics/regions.h>
#include <hardware/blit.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#define XSIZE 11 /* Color box sizes */
#define YSIZE 6
struct GfxBase *GfxBase; /* Export the library pointers */
struct IntuitionBase *IntuitionBase;
struct RastPort *rp; /* Graphics structures */
struct ViewPort *vp;
struct TextAttr TestFont =
{
"topaz.font", /* Standard system font */
8, 0, 0
};
struct Window *w; /* Intuition structures */
struct Screen *screen;
struct IntuiMessage *message;
struct NewScreen ns = {
0, 0, /* start position */
320, 200, 6, /* width, height, depth */
0, 1, /* detail pen, block pen */
HAM, /* Hold and Modify ViewMode */
CUSTOMSCREEN, /* screen type */
&TestFont, /* font to use */
" 256 different out of 4096", /* default title for screen */
NULL /* pointer to additional gadgets */
};
struct NewWindow nw = {
0, 11, /* start position */
320, 186, /* width, height */
-1, -1, /* detail pen, block pen */
MOUSEBUTTONS|CLOSEWINDOW, /* IDCMP flags */
ACTIVATE|WINDOWCLOSE, /* window flags */
NULL, /* pointer to first user gadget */
NULL, /* pointer to user checkmark */
"colors at any given moment", /* window title */
NULL, /* pointer to screen (set below) */
NULL, /* pointer to superbitmap */
0, 0, 320, 186, /* ignored since not sizeable */
CUSTOMSCREEN /* type of screen desired */
};
LONG squarecolor[16 * 16], freecolors[4096-(16*16)];
SHORT squares[16 * 16];
SHORT xpos[16], ypos[16];
char *number[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"A", "B", "C", "D", "E", "F" };
SHORT sStop, cStop, sequence;
BOOL textneeded;
main()
{
ULONG class;
USHORT code, i;
BOOL wheelmode;
for(i=0; i<16; i++) /* Establish color square positions */
{
xpos[i] = (XSIZE + 4) * i + 20;
ypos[i] = (YSIZE + 3) * i + 21;
}
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0);
if (GfxBase == NULL) exit();
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0);
if (IntuitionBase == NULL)
{
CloseLibrary(GfxBase);
exit();
}
screen = (struct Screen *)OpenScreen(&ns);
if (screen == NULL)
{
CloseLibrary(IntuitionBase);
CloseLibrary(GfxBase);
exit();
}
nw.Screen = screen; /* Open window in our new screen */
w = (struct Window *)OpenWindow(&nw);
if (w == NULL)
{
CloseScreen(screen);
CloseLibrary(IntuitionBase);
CloseLibrary(GfxBase);
exit();
}
vp = &screen->ViewPort; /* Set colors in screen's VP */
rp = w->RPort; /* Render into the window's RP */
/* Set the color registers: Black, Red, Green, Blue, White */
SetRGB4(vp, 0, 00, 00, 00);
SetRGB4(vp, 1, 15, 00, 00);
SetRGB4(vp, 2, 00, 15, 00);
SetRGB4(vp, 3, 00, 00, 15);
SetRGB4(vp, 4, 15, 15, 15);
SetBPen(rp, 0); /* Insure clean text */
textneeded = TRUE;
wheelmode = TRUE; /* Start with Color Wheel display */
FOREVER
{ /* Process any and all messages in the queue, then update the */
/* display colors once, then come back here to look at the queue */
/* again. If you see a left-mouse-button-down event, then switch */
/* display modes. If you see a Close-Window-gadget event, then */
/* clean up and exit the program. NOTE: This is a BUSY LOOP so */
/* that the colors will cycle as quickly as possible. */
while((message = (struct IntuiMessage *)GetMsg(w->UserPort)) != NULL)
{
class = message->Class;
code = message->Code;
ReplyMsg(message); /* Can't reply until done using it! */
if(class == CLOSEWINDOW) /* Exit the program */
{
CloseWindow(w);
CloseScreen(screen);
CloseLibrary(IntuitionBase);
CloseLibrary(GfxBase);
exit();
};
if(class == MOUSEBUTTONS && code == SELECTDOWN) /* swap modes */
{
wheelmode = NOT wheelmode;
SetAPen(rp, 0); /* Clear the drawing area */
SetDrMd(rp, JAM1);
RectFill(rp, 3, 12, 318, 183);
textneeded = TRUE;
}
}
if(wheelmode) colorWheel(); else colorFull();
}
}
colorFull() /* Display a ramdomized set of colors */
{
SHORT sChoice, cChoice, usesquare;
LONG usecolor;
if(textneeded) /* First call since mode change? */
{
prompt();
sStop = 255; /* Top of list of squares yet to change */
cStop = 4095 - 256; /* Top of list of colors still needing use */
for(usecolor=0; usecolor<256; usecolor++) /* Initialize colors */
{
usesquare = usecolor;
squares[usesquare] = usesquare;
squarecolor[usesquare] = usecolor;
hamBox(usecolor, xpos[usesquare % 16], ypos[usesquare / 16]);
}
for(usecolor=256; usecolor<4095; usecolor++) /* Ones not yet used */
freecolors[usecolor - 256] = usecolor;
}
/*************************************************************************
* Randomly choose next square to change such that all squares change
* color at least once before any square changes twice. squares[0]
* through squares[sStop] are the square numbers that have not yet
* changed in this pass. RangeRand(r) is an integer function provided
* in "amiga.lib" which produces a random result in the range 0 to
* (r-1) given an integer r in the range 1 to 65535.
************************************************************************/
sChoice = RangeRand(sStop + 1); /* Pick a remaining square */
usesquare = squares[sChoice]; /* Extract square number */
squares[sChoice] = squares[sStop]; /* Swap it with sStop slot */
squares[sStop] = usesquare;
if(NOT sStop--) sStop = 255; /* Only one change per pass */
/************************************************************************
* Randomly choose new color for selected square such that all colors
* are used once before any color is used again, and such that no two
* squares simultaneously have the same color. freecolors[0] through
* freecolors[cStop] are the colors that have not yet been choosen in
* this pass. Note that the 256 colors in use at the end of the
* previous pass are not available for choice in this pass.
***********************************************************************/
cChoice = RangeRand(cStop + 1);
usecolor = freecolors[cChoice];
freecolors[cChoice] = freecolors[cStop];
freecolors[cStop] = squarecolor[usesquare];
squarecolor[usesquare] = usecolor;
if(NOT cStop--) cStop = 4095 - 256;
hamBox(usecolor, xpos[usesquare % 16], ypos[usesquare / 16]);
}
colorWheel() /* Display an ordered set of colors */
{
SHORT i, j;
if(textneeded)
{
prompt();
SetAPen(rp, 2); /* Green pen for green color numbers */
Move(rp, 260, ypos[15]+17);
Text(rp, "Green", 5);
for(i=0; i<16; i++)
{
Move(rp, xpos[i]+3, ypos[15]+17);
Text(rp, number[i], 1);
}
SetAPen(rp, 3); /* Blue pen for blue color numbers */
Move(rp, 4, 18);
Text(rp, "Blue", 4);
for(i=0; i<16; i++)
{
Move(rp, 7, ypos[i]+6);
Text(rp, number[i], 1);
}
SetAPen(rp, 1); /* Red pen for red color numbers */
Move(rp, 271, 100);
Text(rp, "Red", 3);
sequence = 0;
}
SetAPen(rp, 1); /* Identify the red color in use */
SetDrMd(rp, JAM2);
Move(rp, 280, 115);
Text(rp, number[sequence], 1);
for(j=0; j<16; j++) /* Update all of the squares */
for(i=0; i<16; i++)
hamBox((sequence<<8 | i<<4 | j), xpos[i], ypos[j]);
if(++sequence == 16) sequence=0;
}
prompt() /* Display mode changing prompt */
{
SetDrMd(rp, JAM2);
SetAPen(rp, 4);
Move(rp, 23, 183);
Text(rp, "[left mouse button = new mode]", 30);
textneeded = FALSE;
}
/**********************************************************************
* hamBox() -- routine to draw a colored box in Hold and Modify mode.
* Draws a box of size XSIZE by YSIZE with an upper left
* corner at (x,y). The desired color is achieved in 3
* steps on each horizontal line of the box. First we
* set the red component, then the green, then the blue.
* We achieve this by drawing a vertical line of Modify-Red,
* followed by a vertical line of Modify-Green, followed by
* a rectangle of Modify-Blue. Note that the resulting
* color for the first two vertical lines depends upon the
* color(s) of the pixels immediately to the left of that
* line. By the time we reach the rectangle we are assured
* of getting (and maintaining) the desired color because
* we have set all 3 components (R, G, and B) straight from
* the bit map.
***********************************************************************/
hamBox(color, x, y)
LONG color, x, y;
{
SHORT c;
SetDrMd(rp, JAM1); /* Establish Drawing Mode in RastPort */
c=((color & 0xf00)>>8); /* Extract desired Red color component. */
SetAPen(rp, c + 0x20); /* Hold G, B from previous pixel. Set R=n. */
Move(rp, x, y);
Draw(rp, x, y+YSIZE);
x++;
c=((color & 0xf0)>>4); /* Extract desired Green color component. */
SetAPen(rp, c + 0x30); /* Hold R, B from previous pixel. Set G=n. */
Move(rp, x, y);
Draw(rp, x, y+YSIZE);
x++;
c=(color & 0xf); /* Extract desired Blue color component. */
SetAPen(rp, c + 0x10); /* Hold R, G from previous pixel. Set B=n. */
RectFill(rp, x, y, x+XSIZE-2, y+YSIZE);
}